// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

#ifndef _BITSTRING_H_
#define _BITSTRING_H_

#include <stdlib.h>
#include "types.h"

#ifdef __cplusplus
extern "C" {
#endif

/*!
\file
\ingroup	gio
\brief		BitString utility functions 
\details
	Code based on existing 'C' library by Q. Tao.
	Addition of couple of Manchester specific utility functions and doxygen style comments.
\author Qingping Tao, GC Image, LLC., Lincoln, Nebraska, 68508, USA
\author Mark Delderfield, NIBHI, University of Manchester
*/

/*! \brief element-size for the bitstring */
#define BITBULKSIZE (sizeof(unsigned int)*8)

/*! \brief Calculate the number of elements in a bit string */
#define BitStringsize(x) (((x)+BITBULKSIZE-1)/BITBULKSIZE)

/*! \brief Base-type of the BitString */
typedef unsigned int *BitString;

/*!
\brief Create a bit string 
\param [in] numbits the max number of bits 
\returns bitstring or NULL on failure.
 */
BitString new_BitString(long numbits);

/*!
\brief %Set a part from a postion to the end of bit string to 0 
\param [in, out] bs a bit string
\param [in] begin the beginning of the part
\param [in] numbits the number of bits
 */
void BitStringset0(BitString bs, long begin, long numbits);

/*!
\brief %Set all bits from 0 to numbit-1 to 1, set the rest bits to 0 
\param [in, out] bs a bit string
\param [in] numbits the number of bits
 */
void BitStringsetall1(BitString bs, long numbits);

/*!
\brief %Set a bit to 1
\param [in, out] bs a bit string
\param [in] pos the position of a bit
 */
void BitStringset1(BitString bs, long pos);

/*!
\brief Get the number of bits that are 1.
\param [in,out] bs a bit string
\param [in] numbits the number of bits
 */
long BitStringgetnum1s(BitString bs, long numbits);

/*!
\brief Copy a bit string
\param [in] srcbs the source bit string
\param [in, out] desbs the destination bit string
\param [in] numbits the number of bits
 */
void BitStringcopy(BitString srcbs, BitString desbs, long numbits);

/*!
\brief Get the value of a bit
\param [in] bs a bitstring
\param [in] pos a bit position
\returns TRUE or FALSE
 */
BOOL BitStringgetbit(BitString bs, long pos);

/*!
\brief Check if s1 is the super set of s2
\param [in] s1 a bitstring
\param [in] s2 a bitstring
\param [in] numbits the number of bits
\returns 1 if true, 0 if false
 */
int BitStringIsSuperset(BitString s1, BitString s2, long numbits);

/*!
\brief Compare two bit strings. 
\details Otherwise, compare s1 and s2 as two integer arrays in the order of 0, 1, 2...
\param [in] s1 a bitstring
\param [in] s2 a bitstring
\param [in] numbits the number of bits
\returns if s1[i] > s2[i], return 1, otherwise -1, if s1 == s2, return 0.
*/
int BitStringcmp(BitString s1, BitString s2, long numbits);

/*!
\brief AND operation of two BitString
\details Store result in bs1, bs1 = bs1 & bs2
\param [in, out] bs1 the first operand, also used to store result
\param [in] bs2 the second operand bit string
\param [in] numbits the number of bits
 */
void BitStringand(BitString bs1, BitString bs2, long numbits);

/*!
\brief Check if all bits are 0 from begin to end in a bit string.
\param bs a bit string
\param begin the beginning position
\param end the end position
\return 1 if all are 0. Otherwise 0.
 */
int BitStringisall0(BitString bs, long begin, long end);

/*!
\brief Print a bit string from lower bit to higher bit
\param [in] bs a bit string
\param [in] numbits the number of bits
 */
void BitStringprint(BitString bs, long numbits);

/*!
\brief Create a bit string for specified number of bits.
\details Created bitstring initialised as zero for all elements.
\param [in] numbits the number of bits
\param [in, out] allocatedStorage Pointer for the number bytes allocated to the bit string.
\returns BitString
 */
BitString BitString_create(long numbits, int *allocatedStorage);

#ifdef __cplusplus
}
#endif

#endif // _BITSTRING_H_
